using System.Collections.Generic;
using Microsoft.Xna.Framework;
using RebelStar.Engine.Sprites;
using RebelStar.Engine.Units.Equipments;
using RebelStar.Engine.Units.Equipments.Weapons;

namespace RebelStar.Engine.Units
{
    public class Unit
    {
        public const int DEAD_STATE = 0, HIT_STATE = 1, STAY_STATE = 2;

        private readonly UnitSprite sprite;
        private readonly List<EquipmentSlot> slots;
        private int sight = 3;
        private int ap = 10;
        private int hp = 10;

        private Point position;
        private int currentAP;
        private int currentState;

        public Unit(UnitSprite sprite, Point position)
        {
            this.sprite = sprite;
            this.position = position;
            this.slots = new List<EquipmentSlot>(2);
            this.slots.Add(new EquipmentSlot("Left hand"));
            this.slots.Add(new EquipmentSlot("Right hand"));

            this.ResetParameters();
        }

        public UnitSprite Sprite
        {
            get { return sprite; }
        }
        public int Sight
        {
            get { return sight; }
        }
        /// <summary>
        /// Action points
        /// </summary>
        public int AP
        {
            get { return ap; }
        }
        /// <summary>
        /// Health points
        /// </summary>
        public int HP
        {
            get { return hp; }
            private set
            {
                hp = value;
                this.CurrentState = this.IsAlive ? HIT_STATE : DEAD_STATE;
            }
        }
        public Point Position
        {
            get { return position; }
        }
        public int CurrentAP
        {
            get { return currentAP; }
            private set { currentAP = value; }
        }
        public int CurrentState
        {
            get { return currentState; }
            private set { currentState = value; }
        }

        public bool IsAlive
        {
            get
            {
                return hp > 0;
            }
        }
        public List<EquipmentSlot> Slots
        {
            get { return slots; }
        }
        public EquipmentSlot DefaultSlot
        {
            get
            {
                if (slots.Count > 0) return slots[1];
                else return null;
            }
        }

        internal Point CalculateMove(MoveType type)
        {
            Point res = this.position;
            switch (type)
            {
                case MoveType.LeftUp:
                    if (res.Y % 2 == 0)
                        res.X--;
                    res.Y--;
                    break;
                case MoveType.Up:
                    res.Y -= 2;
                    break;
                case MoveType.RightUp:
                    if (res.Y % 2 == 1)
                        res.X++;
                    res.Y--;
                    break;
                case MoveType.Left:
                    res.X--;
                    break;
                case MoveType.Right:
                    res.X++;
                    break;
                case MoveType.LeftDown:
                    if (res.Y % 2 == 0)
                        res.X--;
                    res.Y++;
                    break;
                case MoveType.Down:
                    res.Y += 2;
                    break;
                case MoveType.RightDown:
                    if (res.Y % 2 == 1)
                        res.X++;
                    res.Y++;
                    break;
            }
            return res;
        }
        internal void Move(MoveType type, int ap)
        {
            currentAP -= ap;
            this.position = this.CalculateMove(type);
        }
        internal void ResetParameters()
        {
            if (this.IsAlive)
            {
                this.currentAP = ap;
                this.currentState = STAY_STATE;
            } 
        }
        internal bool CanFire(Weapon weapon, Action action)
        {
            if (weapon == null) return false;
            return this.IsAlive && this.currentAP >= action.AP;
        }
        public void Fire(Weapon weapon, Action action)
        {
            weapon.Fire(action);
            this.CurrentAP -= action.AP;
        }
        public void Hit(int pow)
        {
            this.HP -= pow;
        }
    }
}